package io.reactivex.rxohos2;


import com.polidea.rxohosble2.LogConstants;
import com.polidea.rxohosble2.LogOptions;
import com.polidea.rxohosble2.RxBleClient;
import com.polidea.rxohosble2.RxBleConnection;
import com.polidea.rxohosble2.sample.util.HexString;
import com.polidea.rxohosble2.scan.ScanFilter;
import com.polidea.rxohosble2.scan.ScanResult;
import com.polidea.rxohosble2.scan.ScanSettings;
import io.reactivex.Observable;
import io.reactivex.disposables.Disposable;
import ohos.aafwk.ability.delegation.AbilityDelegatorRegistry;
import ohos.app.Context;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.util.UUID;

public class RxBleClientTest {

    Context context;

    @Before
    public void setUp() throws Exception {
        context = AbilityDelegatorRegistry.getAbilityDelegator().getAppContext();
    }

    @Test
    public void updateLogOptions() {
        try {
            RxBleClient.updateLogOptions(new LogOptions.Builder()
                    .setLogLevel(LogConstants.VERBOSE)
                    .setMacAddressLogSetting(LogConstants.MAC_ADDRESS_FULL)
                    .setUuidsLogSetting(LogConstants.UUIDS_FULL)
                    .setShouldLogAttributeValues(true)
                    .build()
            );
        } catch (Exception e) {
            Assert.fail();
        }
    }

    @Test
    public void create() {
        RxBleClient client = RxBleClient.create(context);
        Assert.assertNotNull(client);
    }

    @Test
    public void scanBleDevices() {
        RxBleClient client = RxBleClient.create(context);
        Observable<ScanResult> scanResultObservable = client.scanBleDevices(new ScanSettings.Builder()
                        .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
                        .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
                        .build(),
                new ScanFilter.Builder()
//                            .setDeviceAddress("B4:99:4C:34:DC:8B")
                        // add custom filters if needed
                        .build()
        );

        Assert.assertNotNull(scanResultObservable);
    }

    @Test
    public void connection() {

        String address = "18:93:7F:E8:2F:14";
        String deviceName = "ZKTeco";
        ScanResult scanResult = new ScanResult(address);
        RxBleClient client = RxBleClient.create(context);
        Observable<RxBleConnection> connection = client.getBleDevice(address).establishConnection(true);

        Assert.assertNotNull(connection);
//        BlePeripheralDevice.createInstance()
//        client.getBondedDevices()
//        client.scanBleDevices()

    }

    @Test
    public void observeStateChanges() {
        RxBleClient client = RxBleClient.create(context);
        Observable<RxBleClient.State> stateObservable = client.observeStateChanges();
        Assert.assertNotNull(stateObservable);
    }


    @Test
    public void discovery() {

        String address = "18:93:7F:E8:2F:14";
        String deviceName = "ZKTeco";
        RxBleClient client = RxBleClient.create(context);
        Observable<RxBleConnection> connection = client.getBleDevice(address).establishConnection(true);
        Disposable disposable = connection.flatMapSingle(RxBleConnection::discoverServices).subscribe();
//        disposable.dispose();

        Assert.assertNotNull(disposable);

    }

    @Test
    public void disconnect() {

        String address = "18:93:7F:E8:2F:14";
        String deviceName = "ZKTeco";
        RxBleClient client = RxBleClient.create(context);
        Observable<RxBleConnection> connection = client.getBleDevice(address).establishConnection(true);
        Disposable disposable = connection.flatMapSingle(RxBleConnection::discoverServices).subscribe();
        disposable.dispose();

        Assert.assertNotNull(disposable);

    }

    @Test
    public void writeCharacteristic() {

        String address = "18:93:7F:E8:2F:14";
        String deviceName = "ZKTeco";
        RxBleClient client = RxBleClient.create(context);
        Observable<RxBleConnection> connection = client.getBleDevice(address).establishConnection(true);
        Disposable disposable = connection.firstOrError()
                .flatMap(rxBleConnection -> rxBleConnection.writeCharacteristic(UUID.randomUUID(), HexString.hexToBytes(deviceName)))
                .subscribe(success -> Assert.assertTrue(true));

        Assert.assertNotNull(disposable);

    }

    @Test
    public void readCharacteristic() {

        String address = "18:93:7F:E8:2F:14";
        String deviceName = "ZKTeco";
        RxBleClient client = RxBleClient.create(context);
        Observable<RxBleConnection> connection = client.getBleDevice(address).establishConnection(true);
        Disposable disposable = connection.firstOrError()
                .flatMap(rxBleConnection -> rxBleConnection.readCharacteristic(UUID.randomUUID()))
                .subscribe(success -> {
                    Assert.assertTrue(true);
                });

        Assert.assertNotNull(disposable);

    }

    @Test
    public void setupNotification() {

        String address = "18:93:7F:E8:2F:14";
        String deviceName = "ZKTeco";
        RxBleClient client = RxBleClient.create(context);
        Observable<RxBleConnection> connection = client.getBleDevice(address).establishConnection(true);
        Disposable disposable = connection
                .flatMap(rxBleConnection -> rxBleConnection.setupNotification(UUID.randomUUID()))
                .subscribe(success -> Assert.assertTrue(true));

        Assert.assertNotNull(disposable);

    }

    @Test
    public void getCharacteristic() {

        String address = "18:93:7F:E8:2F:14";
        String deviceName = "ZKTeco";
        RxBleClient client = RxBleClient.create(context);
        Observable<RxBleConnection> connection = client.getBleDevice(address).establishConnection(true);
        Disposable disposable = connection
                .flatMapSingle(RxBleConnection::discoverServices)
                .flatMapSingle(rxBleConnection -> rxBleConnection.getCharacteristic(UUID.randomUUID()))
                .subscribe(success -> Assert.assertTrue(true));

        Assert.assertNotNull(disposable);

    }
}